from sys import argv
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

class MyPyOpenGLTest:
    # 初始化OpenGL环境，指定显示模式以及用于绘图的函数
    def __init__(self, width=640, height=480,
                 title='PyOpenGL旋转立方体'.encode('gbk')):
        glutInit(argv)
        # 使用RGBA颜色、双缓冲、深度缓冲Z-Buffer
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
        # 设置图形窗口初始大小和位置，然后创建图形窗口，顺序不能变
        glutInitWindowSize(width, height)
        glutInitWindowPosition(400, 200)
        glutCreateWindow(title)
        # 指定绘制图形时执行的方法
        glutDisplayFunc(self.draw)
        # 指定调整窗口大小时执行的方法
        glutReshapeFunc(self.reshape)
        # 指定系统空闲时执行的方法，是本动画的重要基础
        glutIdleFunc(self.draw)

        # 初始化窗口背景为白色
        glClearColor(1, 1, 1, 1)
        # 启用纵深测试，设置深度，注意线框立方体旋转时远处消失的效果
        glClearDepth(1)
        glEnable(GL_DEPTH_TEST)
        glDepthFunc(GL_LEQUAL)
        # 使用颜色材质
        glEnable(GL_COLOR_MATERIAL)
        # 设置光滑渲染
        glEnable(GL_BLEND)
        glShadeModel(GL_SMOOTH)
        glEnable(GL_POINT_SMOOTH)
        glEnable(GL_LINE_SMOOTH)
        glEnable(GL_POLYGON_SMOOTH)
        # 设置反走样/抗锯齿算法
        glHint(GL_POINT_SMOOTH_HINT, GL_NICEST)
        glHint(GL_LINE_SMOOTH_HINT, GL_NICEST)
        glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST)


        # 四棱锥旋转角度
        self.angle4 = 0
        # 立方体旋转角度
        self.angle6 = 0
        # 四棱锥顶点坐标、绘制侧表面时的顶点顺序、每个面上的顶点颜色
        self.points4 = ((0,1,0), (-1,-1,1), (1,-1,1), (1,-1,-1),
                        (-1,-1,-1))
        self.vertice4 = ((0,1,2), (0,2,3), (0,3,4), (0,4,1))
        self.colors4 = ((1,0,0), (0,1,0), (0,0,1), (1,1,0))
        # 立方体顶点坐标、绘制表面时的顶点顺序、每个面上的顶点颜色
        self.points6 = ((1,1,-1), (-1,1,-1), (-1,1,1), (1,1,1),
                        (1,-1,1), (-1,-1,1), (-1,-1,-1), (1,-1,-1))
        self.vertice6 = ((0,1,2,3), (4,5,6,7), (3,2,5,4),
                         (7,6,1,0), (2,1,6,5), (0,3,4,7))
        self.colors6 = ((0,1,0), (1,0.5,0), (1,0,0),
                        (1,1,0), (0,0,1), (1,0,1))

    # 调成图形窗口大小时执行的方法
    def reshape(self, w, h):

        if h == 0:
            h = 1
        ratio = w / h
        glViewport(0, 0, w, h)

        # 切换到透视投影矩阵
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()

        gluPerspective(45, ratio, 0.1, 10)

        # 切换到模型观察矩阵
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

    def draw_pyramind(self):
        # 绘制四棱锥侧面
        glBegin(GL_TRIANGLES)
        for index, vertice in enumerate(self.vertice4):
            glColor3fv(self.colors4[index])
            for i in vertice:
                glVertex3fv(self.points4[i])
        glEnd()

        # 绘制四棱锥底面
        glBegin(GL_QUADS)
        glColor3f(0, 0, 0)
        for vertex in self.points4[1:]:
            glVertex3fv(vertex)
        glEnd()


    def draw_cube(self):
        glBegin(GL_QUADS)
        for index, vertice in enumerate(self.vertice6):
            glColor3fv(self.colors6[index])
            for i in vertice:
                glVertex3fv(self.points6[i])
        glEnd()
        
    # 自己的绘图方法，本程序的关键
    def draw(self):
        # 每次绘制图形之前清除颜色缓冲区和深度缓冲区中的信息
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glLoadIdentity()
        glTranslatef(-1.5, 0, -6)
        glRotatef(self.angle4, 1, 1, 0)
        self.draw_pyramind()

        glLoadIdentity()
        glTranslatef(1.5, 0, -6)
        glRotatef(self.angle6, 1, 1, 1)
        self.draw_cube()

        # 修改旋转角度
        self.angle4 = self.angle4 + 0.15
        self.angle6 = self.angle6 - 0.1

        # 交换缓冲区，更新图形
        glutSwapBuffers()

    # 消息主循环
    def mainloop(self):
        glutMainLoop()

if __name__ == '__main__':
    # 创建窗口对象，启动消息主循环
    MyPyOpenGLTest().mainloop()
